package com.tengju.bff.interfaces.app.domination.assembler;

import com.google.common.collect.Lists;
import com.tengju.bff.interfaces.app.domination.vo.*;
import com.tengju.bff.interfaces.manage.crm.user.vo.NicknameVO;
import com.tengju.bff.interfaces.shared.AmountType;
import com.tengju.bff.interfaces.shared.AmountVO;
import com.tengju.bff.interfaces.shared.MobileVO;
import com.tengju.data.domain.model.clickhouse.star.DominationMemberNew;
import com.tengju.data.domain.model.clickhouse.star.DominationUpComing;
import com.tengju.data.domain.model.clickhouse.star.StarChangeNoticeRecord;
import com.tengju.data.domain.model.clickhouse.star.UpgradingDetail;
import com.tengju.data.domain.model.user.*;
import com.tengju.data.domain.shared.DateUtil;
import com.tengju.user.domain.model.doc.UserDocument;
import com.tengju.user.domain.model.star.StarIndicatorType;
import com.tengju.user.domain.model.user.DominationMemberNote;
import com.tengju.user.domain.model.user.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
public class DominationAssembler {

    public static List<DominationMemberDetailVO> assemblerToVO(List<DominationDetail> dominationDetails,Page<UserDocument> userDocuments,List<DominationMemberNote> dominationMemberNoteList ) {


        Map<Long, UserDocument> userDocumentMap =
                userDocuments.stream().collect(Collectors.toMap(UserDocument::getIdCode, Function.identity()));

        Map<com.tengju.user.domain.model.user.UserIdCode, String> remarkMap =
                dominationMemberNoteList.stream().collect(Collectors.toMap(DominationMemberNote::getSubordinateId, DominationMemberNote::getRemark));

        ArrayList<DominationMemberDetailVO> dominationMemberDetailVOList = Lists.newArrayList();

        for (DominationDetail dominationDetail : dominationDetails) {
            DominationMemberDetailVO dominationMemberDetailVO = new DominationMemberDetailVO();
            UserDocument userDocument = userDocumentMap
                    .get(dominationDetail.getIdCode().getValue());

            if (userDocument == null) {
                log.error("es数据延迟，id_code:{}",dominationDetail.getIdCode().getValue());
            }

            AmountVO index = new AmountVO(AmountType.INDEX, dominationDetail.getCurrentMonthAchievement());
            dominationMemberDetailVO.setIdCode(dominationDetail.getIdCode().getValue());
            dominationMemberDetailVO.setNickname(new NicknameVO(Optional.ofNullable(userDocument).map(UserDocument::getNickName).orElse("")
                    ,Optional.ofNullable(userDocument).map(UserDocument::getMobile).orElse("")));
            dominationMemberDetailVO.setMobile(new MobileVO(Optional.ofNullable(userDocument).map(UserDocument::getMobile).orElse("")));
            dominationMemberDetailVO.setHeadImage(Optional.ofNullable(userDocument).map(UserDocument::getHeadImage).orElse(""));
            dominationMemberDetailVO.setStarLevel(Optional.ofNullable(userDocument).map(UserDocument::getStarLevel).orElse(null));
            dominationMemberDetailVO.setStarLevelDesc(Optional.ofNullable(StarLevelEnum.parseByStarLevel(Optional.ofNullable(userDocument).map(UserDocument::getStarLevel).orElse(null)))
                    .map(StarLevelEnum::getDesc).orElse(""));
            dominationMemberDetailVO.setMarketIndex(index);
            dominationMemberDetailVO.setServiceProviderQuantity(dominationDetail.serviceProviderNum());
            dominationMemberDetailVO.setDealerQuantity(dominationDetail.getDominationDealerNum());
            dominationMemberDetailVO.setRegisterTime(dominationDetail.registerTimeStr());
            dominationMemberDetailVO.setRemark(
                    remarkMap.get(new com.tengju.user.domain.model.user.UserIdCode(dominationDetail.getIdCode().getValue())));
            dominationMemberDetailVO.setUserLevelFourCnt(dominationDetail.getUserLevelFourCnt());
            dominationMemberDetailVO.setUserLevelThreeCnt(dominationDetail.getUserLevelThreeCnt());
            dominationMemberDetailVO.setUserLevelTwoCnt(dominationDetail.getUserLevelTwoCnt());
            dominationMemberDetailVOList.add(dominationMemberDetailVO);

        }
        return dominationMemberDetailVOList;
    }

    public static DominationMemberNumVO assemblerToVO(Map<StarRoleEnum, Map<StarLevelEnum, Integer>> dominationTeamMemberNum) {


        List<DominationMemberNumDetailVO> numList = Lists.newArrayList();

        for (Map.Entry<StarRoleEnum, Map<StarLevelEnum, Integer>> entry : dominationTeamMemberNum.entrySet()) {
            DominationMemberNumDetailVO dominationMemberNumDetailVO = new DominationMemberNumDetailVO();
            StarRoleEnum starRole = entry.getKey();
            Map<StarLevelEnum, Integer> numDetail = entry.getValue();

            dominationMemberNumDetailVO.setStarRole(starRole.getCode());
            dominationMemberNumDetailVO.setStarRoleDesc(starRole.getDesc());

            int total = 0;
            List<StarLevelNumVO> starLevelNumVOList = Lists.newArrayList();
            for (Map.Entry<StarLevelEnum, Integer> detailEntry : numDetail.entrySet()) {
                total = total + detailEntry.getValue();
                starLevelNumVOList.add(StarLevelNumVO.of(detailEntry.getKey(), detailEntry.getValue()));
            }
            dominationMemberNumDetailVO.setTotalNum(total);
            dominationMemberNumDetailVO.setNumDetail(starLevelNumVOList);
            numList.add(dominationMemberNumDetailVO);
        }
        return new DominationMemberNumVO(numList);

    }

    public static NewMemberInfoNumVO assemblerToVO(DominationMemberNew dominationMemberNew, List<UpgradingDetail> upgradingDetails,List<UserInfo> userInfos) {

        Map<Long, UserInfo> userInfoMap = userInfos.stream()
                .collect(Collectors.toMap(userInfo -> userInfo.getIdCode().getValue(), Function.identity()));

        List<NewMemberInfoVO> newMemberInfoVOList = Lists.newArrayList();
        for (UpgradingDetail upgradingDetail : upgradingDetails) {
            UserInfo userInfo = userInfoMap.get(upgradingDetail.getIdCode().getValue());
            NewMemberInfoVO newMemberInfoVO = new NewMemberInfoVO(new NicknameVO(Optional.ofNullable(userInfo).map(UserInfo::getNickName).orElse(null),
                        Optional.ofNullable(userInfo).map(UserInfo::getWholePhoneNumber).orElse(null)),
                    Optional.ofNullable(userInfo).map(UserInfo::getHeadImage).orElse(""),
                    upgradingDetail.getUpgradingTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
                    upgradingDetail.getStarLevel().getDesc(),
                    DateUtil.getDuration(upgradingDetail.getUpgradingTime()));
            newMemberInfoVOList.add(newMemberInfoVO);
        }

        return new NewMemberInfoNumVO(dominationMemberNew.getNewEcNum(),
                dominationMemberNew.getNewCityStarOneNum(),
                dominationMemberNew.getNewCityStarTwoNum(),
                dominationMemberNew.getNewCityStarThreeNum(),
                dominationMemberNew.getNewCityStarFourNum(),
                dominationMemberNew.getNewDealerNum(),
                newMemberInfoVOList);

    }

    public static List<NewMemberDetailVO> assemblerToVO( List<UpgradingDetail> upgradingDetails,List<UserInfo> userInfos,Page<UserDocument> userDocuments){

        Map<Long, UserInfo> userInfoMap = userInfos.stream()
                .collect(Collectors.toMap(userInfo-> userInfo.getUserIdCode().getValue(), Function.identity()));
        Map<Long, UserDocument> userDocumentMap = userDocuments.stream().
                collect(Collectors.toMap(UserDocument::getIdCode, Function.identity()));

        List<NewMemberDetailVO> newMemberDetailVOList = Lists.newArrayList();

        for (UpgradingDetail upgradingDetail : upgradingDetails) {

            UserInfo userInfo = userInfoMap.get(upgradingDetail.getIdCode().getValue());
            UserDocument userDocument = userDocumentMap.get(upgradingDetail.getIdCode().getValue());

            //所属运营商
            UserInfo operator = userInfoMap.get(Optional.ofNullable(userDocument).map(UserDocument::getOwnerGenOperatorIdCode).orElse(null));
            //所属服务商
            UserInfo serviceProvider = userInfoMap.get(Optional.ofNullable(userDocument).map(UserDocument::getOwnerCityIdCode).orElse(null));
            //所属代理
            UserInfo parent = userInfoMap.get(Optional.ofNullable(userDocument).map(UserDocument::getParentIdCode).orElse(null));

            OwnerLeaderVO ownerLeaderVO = OwnerLeaderAssembler.assemblerToVO(userInfo.starLevel(), operator, serviceProvider, parent);

            NewMemberDetailVO newMemberDetailVO = new NewMemberDetailVO(new NicknameVO(userInfo.getNickName(),userInfo.getWholePhoneNumber()),
                    userInfo.getHeadImage(),
                    userInfo.starLevel().getCode(),
                    userInfo.starLevel().getDesc(),
                    ownerLeaderVO.getBelongOperatorName(),
                    ownerLeaderVO.getBelongServiceProviderName(),
                    ownerLeaderVO.getBelongDealerName(),
                    upgradingDetail.getUpgradingTime() == null ?
                            "" : upgradingDetail.getUpgradingTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

            newMemberDetailVOList.add(newMemberDetailVO);
        }

        return newMemberDetailVOList;

    }


    public static MemberUpcomingNumVO assemblerToVO(DominationUpComing dominationUpComing,List<StarChangeNoticeRecord> operatorNoticeRecords,List<StarChangeNoticeRecord> serviceProviderNoticeRecords,List<StarChangeNoticeRecord> dealerNoticeRecords,List<UserInfo> userInfoList,Map<UserIdCode, List<StarIndicator>> notReachIndicator ) {


        HashMap<UserIdCode, UserInfo> userInfoMap = new HashMap<>();
        for (UserInfo userInfo : userInfoList) {
            UserIdCode idCode = new UserIdCode(userInfo.getUserIdCode().getValue());
            userInfoMap.put(idCode,userInfo);
        }

        List<MemberUpComingInfoVO> operator = convertToVO(operatorNoticeRecords, notReachIndicator, userInfoMap);

        List<MemberUpComingInfoVO> serviceProvider = convertToVO(serviceProviderNoticeRecords, notReachIndicator, userInfoMap);

        List<MemberUpComingInfoVO> dealer = convertToVO(dealerNoticeRecords, notReachIndicator, userInfoMap);

        MemberUpcomingNumDetailVO operatorDetailVO = new MemberUpcomingNumDetailVO(dominationUpComing.operatorNum(), operator);

        MemberUpcomingNumDetailVO serviceProviderDetailVO = new MemberUpcomingNumDetailVO(dominationUpComing.serviceProviderNum(), serviceProvider);

        MemberUpcomingNumDetailVO dealerDetailVO = new MemberUpcomingNumDetailVO(dominationUpComing.dealerNum(), dealer);

        return new MemberUpcomingNumVO(operatorDetailVO,
                serviceProviderDetailVO,
                dealerDetailVO);


    }

    private static List<MemberUpComingInfoVO> convertToVO(List<StarChangeNoticeRecord> operatorNoticeRecords, Map<UserIdCode, List<StarIndicator>> notReachIndicator, HashMap<UserIdCode, UserInfo> userInfoMap) {
        List<MemberUpComingInfoVO> operator = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(operatorNoticeRecords)) {
            for (StarChangeNoticeRecord starChangeNoticeRecord : operatorNoticeRecords) {
                UserIdCode idCode = starChangeNoticeRecord.getIdCode();
                MemberUpComingInfoVO memberUpComingInfoVO =
                        assemblerToVO(userInfoMap.get(idCode), starChangeNoticeRecord, notReachIndicator.get(idCode));
                operator.add(memberUpComingInfoVO);
            }
        }
        return operator;
    }

    public static MemberUpComingInfoVO assemblerToVO(UserInfo userInfo,StarChangeNoticeRecord starChangeNoticeRecord,List<StarIndicator> starIndicatorList) {

        List<UpcomingIndicatorVO> upcomingIndicatorVOList = 
                starIndicatorList.stream()
                        .map(starIndicator -> DominationAssembler.assemblerToVO(starIndicator,starChangeNoticeRecord.getTargetStarLevel()))
                        .collect(Collectors.toList());

        return new MemberUpComingInfoVO(new NicknameVO(Optional.ofNullable(userInfo).map(UserInfo::getNickName).orElse(null),
                    Optional.ofNullable(userInfo).map(UserInfo::getWholePhoneNumber).orElse(null)),
                Optional.ofNullable(userInfo).map(UserInfo::getHeadImage).orElse(""),
                starChangeNoticeRecord.getTargetStarLevel().getDesc(),
                upcomingIndicatorVOList);
    }

    public static UpcomingIndicatorVO assemblerToVO(StarIndicator starIndicator,StarLevelEnum targetStarLevel) {

        BigDecimal indicatorDiff = starIndicator.getIndicatorTargetValue().subtract(starIndicator.getIndicatorValue());

        String indicatorDiffStr = StarIndicatorType.indicatorDiff(starIndicator.getStarIndicatorType(), indicatorDiff,
                starIndicator.getIndicatorTargetValue(), com.tengju.user.domain.model.user.StarLevelEnum.parseByCode(targetStarLevel.getCode()));

        return new UpcomingIndicatorVO(starIndicator.getStarIndicatorType().getDesc(),
                starIndicator.getIndicatorTargetValue().doubleValue(),
                starIndicator.getIndicatorValue().doubleValue(),
                indicatorDiffStr);

    }

    public static MemberUpcomingDetailVO assemblerToVO(StarChangeNoticeRecord starChangeNoticeRecord ,Page<UserDocument> userDocuments ,Map<UserIdCode, List<StarIndicator>> notReachIndicator,List<UserInfo> userInfos) {

        Map<Long, UserDocument> userDocumentMap = userDocuments.stream()
                .collect(Collectors.toMap(UserDocument::getIdCode, Function.identity()));

        Map<com.tengju.user.domain.model.user.UserIdCode, UserInfo> userInfoMap =
                userInfos.stream().collect(Collectors.toMap(UserInfo::getIdCode, Function.identity()));

        UserDocument userDocument = userDocumentMap.get(starChangeNoticeRecord.getIdCode().getValue());
        List<StarIndicator> starIndicators = notReachIndicator.get(starChangeNoticeRecord.getIdCode());

        List<UpcomingIndicatorVO> upcomingIndicatorList = starIndicators.stream()
                .map(starIndicator -> DominationAssembler.assemblerToVO(starIndicator,starChangeNoticeRecord.getTargetStarLevel()))
                .collect(Collectors.toList());


        UserInfo belongOperator = null;
        if (userDocument != null && userDocument.getOwnerGenOperatorIdCode() != null && userDocument.getOwnerGenOperatorIdCode() > 0) {
            belongOperator = userInfoMap.get(new com.tengju.user.domain.model.user.UserIdCode(userDocument.getOwnerGenOperatorIdCode()));
        }

        UserInfo belongServiceProvider = null;
        if (userDocument != null && userDocument.getOwnerCityIdCode() != null && userDocument.getOwnerCityIdCode() > 0) {
            belongServiceProvider = userInfoMap.get(new com.tengju.user.domain.model.user.UserIdCode(userDocument.getOwnerCityIdCode()));
        }

        UserInfo parent = null;
        if (userDocument != null && userDocument.getParentIdCode() != null && userDocument.getParentIdCode() > 0) {
            parent = userInfoMap.get(new com.tengju.user.domain.model.user.UserIdCode(userDocument.getParentIdCode()));
        }

        OwnerLeaderVO ownerLeaderVO = OwnerLeaderAssembler.assemblerToVO(com.tengju.user.domain.model.user.StarLevelEnum.parseByCode(
                Optional.ofNullable(userDocument).map(UserDocument::getStarLevel).orElse(0)),
                belongOperator, belongServiceProvider, parent);

        StarLevelEnum currentStarLevel = StarLevelEnum.parseByStarLevel(
                Optional.ofNullable(userDocument).map(UserDocument::getStarLevel).orElse(0));

        return new MemberUpcomingDetailVO(
                new NicknameVO(Optional.ofNullable(userDocument).map(UserDocument::getNickName).orElse(""),
                        Optional.ofNullable(userDocument).map(UserDocument::getNickName).orElse("")),
                Optional.ofNullable(userDocument).map(UserDocument::getHeadImage).orElse(""),
                Optional.ofNullable(currentStarLevel).map(StarLevelEnum::getCode).orElse(null),
                Optional.ofNullable(currentStarLevel).map(StarLevelEnum::getDesc).orElse(""),
                starChangeNoticeRecord.getTargetStarLevel().getDesc(),
                ownerLeaderVO.getBelongOperatorName(),
                ownerLeaderVO.getBelongServiceProviderName(),
                ownerLeaderVO.getBelongDealerName(),
                upcomingIndicatorList);

    }


}